package com.baiyang.server.config.provider;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import com.baiyang.server.model.system.User;
import com.baiyang.server.model.system.UserRole;
import com.baiyang.server.service.system.UserRoleService;
import com.baiyang.server.service.system.UserService;
import com.baiyang.server.tools.Data;
import com.baiyang.server.tools.DataTool;

/**
 * 自定义认证过程
 * @author XVX
 *
 */
@Component
public class MyAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
	@Autowired
	private UserService userService = null;
	@Autowired
	private UserRoleService userRoleService = null;
	@Autowired
	private PasswordEncoder passwordEncoder = null;
	/**
	 * 附加认证过程  --  进行用户信息认证
	 */
	@Override
	protected void additionalAuthenticationChecks(UserDetails userDetails,
			UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
		// TODO Auto-generated method stub
		System.out.println("附加认证过程");
	    if (authentication.getCredentials() == null) {
	        logger.debug("Authentication failed: no credentials provided");

	        throw new BadCredentialsException(messages.getMessage(
	            "AbstractUserDetailsAuthenticationProvider.badCredentials",
	            "Bad credentials"));
	      }

	      String presentedPassword = authentication.getCredentials().toString();
	      // rawPassword--原始密码    encodedPassword--被加密后的密码
	      if (!passwordEncoder.matches(presentedPassword, passwordEncoder.encode(userDetails.getPassword()))) {

	        throw new BadCredentialsException(messages.getMessage(
	            "MyAuthenticationProvider.badCredentials",
	            Data.ERROR.PASSWORD));
	      }
	}
	/**
	 * @apiNote 获取用户信息 首先判断该用户是否存在，然后根据用户角色进行判断具体验证方式
	 * @author XVX
	 * @version 1
	 * @since 2021-11-18
	 */
	@Override
	protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
			throws AuthenticationException {
		// TODO Auto-generated method stub
		User user = new User();
		user.setUserName(username);
		user = userService.selectOneByUserName(username);
		UserDetail detail = new UserDetail();
		if(user != null) {
			List<UserRole> userRoles = userRoleService.selectByUserId(user.getId());
			if (userRoles != null && userRoles.size() != 0) { 
				// 是超级管理员
				if(isAdmin(userRoles)) {
					MyUsernamePasswordAuthenticationToken authenticationToken = (MyUsernamePasswordAuthenticationToken) authentication;
					MyWebAuthenticationDetails authenticationDetails = (MyWebAuthenticationDetails) authentication.getDetails();
					HttpSession session = authenticationDetails.getSession();
					if(session == null) {
						
				        throw new BadCredentialsException(messages.getMessage("MyAuthenticationProvider.badCredentials",
					            Data.ERROR.VERCODE));
					}
					Object ver = session.getAttribute(Data.Session.VER_CODE);
					String verCode = ver==null?"":String.valueOf(ver);
					if(DataTool.isBlank(verCode)||DataTool.isBlank(authenticationToken.getVerCode())||!verCode.equals(authenticationToken.getVerCode())) {
				        throw new BadCredentialsException(messages.getMessage("MyAuthenticationProvider.badCredentials",
					            Data.ERROR.VERCODE));
					}
					session.removeAttribute(Data.Session.VER_CODE);
				}
				/**
				 * 配置用户权限 
				 * todo
				 */
				List<Authority> authorities = new ArrayList<Authority>();
				//根据用户角色获取访问权限
				
				userRoles.forEach(e->{
					Authority authority = new Authority(e.getRoleId());
					authorities.add(authority);
				});
				detail.setAuthorities(authorities);
			}
			detail.setUserName(user.getUserName());
			detail.setPassword(user.getPassword());
			detail.setUser(user);
		}else {
	        throw new BadCredentialsException(messages.getMessage("MyAuthenticationProvider.badCredentials",
		            Data.ERROR.USERNAME));
		}
		return detail;
	}
	
	/**
	 * @apiNote 判断用户是否是管理员
	 * @param userRoles
	 * @return
	 */
	private boolean isAdmin(List<UserRole> userRoles) {
		for (UserRole userRole : userRoles) {
			if(Data.DataDictionary.SUPER_ADMIN_ROLE_ID.equals(userRole.getRoleId())) {
				return true;
			}
		}
		return false;
	}
	
}
